home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / c / pcw.zip / REORDER.BAK < prev    next >
Text File  |  1990-12-18  |  19KB  |  440 lines

  1. /***********************************************************/
  2. /* File Id.                  Reorder.C.                    */
  3. /* Author.                   Stan Milam.                   */
  4. /* Date Written.             02/06/89.                     */
  5. /*                                                         */
  6. /*         (c) Copyright 1989, 1990 by Stan Milam          */
  7. /*                                                         */
  8. /* Comments:  The functions in this file control & maintain*/
  9. /* a list of all windows being used.  When a window is     */
  10. /* pushed it is added to the list and occupies the first   */
  11. /* position in the list.  When a window is poped it is re- */
  12. /* moved from the list, hidden and deleted.  If a window in*/
  13. /* the middle or end of the list is addressed that window  */
  14. /* is floated to the top of the list recursively.  The     */
  15. /* variable, topwnd, always points to the beginning of the */
  16. /* list.                                                   */
  17. /***********************************************************/
  18.  
  19. #if __TURBOC__ || __ZTC__
  20. #   define _fmalloc farmalloc
  21. #   define _ffree   farfree
  22. #   if __TURBOC__
  23. #      include <alloc.h>
  24. #   endif
  25. #else
  26. #   include <malloc.h>
  27. #endif
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <dos.h>
  32. #include "pcw.i"
  33. #include "pcwproto.h"
  34.  
  35. #define USER   1                            /* User hidden attribute */
  36. #define SYSTEM 2                            /* System hidden attribute */
  37.  
  38. /* Function Prototypes of local functions */
  39.  
  40. static int  chk_wnds(WNDPTR *wnd);
  41. static int  hide_wnd(WNDPTR *wnd, int attribute);
  42. static int  show_wnd(WNDPTR *wnd, int attribute);
  43. static int  wnd_overlap(WNDPTR *wnd1, WNDPTR *wnd2);
  44. static void level_wnds(WNDPTR *wnd);
  45. static void remove_from_list(WNDPTR *wnd);
  46. static void reshow_wnds(WNDPTR *wnd);
  47. static void insert_first_in_list(WNDPTR *wnd);
  48. static void change_wnd_position(WNDPTR *wnd,int row,int col,int cl,int rw);
  49.  
  50. static WNDPTR *topwnd = (WNDPTR *) NULL;
  51.  
  52. /************************************************************/
  53. /*                      Get_Active_Wnd                      */
  54. /*                                                          */
  55. /* Returns the most active (top) window.  If no windows are */
  56. /* up returns NULL.                                         */
  57. /************************************************************/
  58.  
  59. WNDPTR *get_active_wnd(void) {
  60.  
  61.    return(topwnd);
  62. }
  63.  
  64. /************************************************************/
  65. /*                          Wndmove                         */
  66. /*                                                          */
  67. /* This function will handle moving a window from one place */
  68. /* on the screen to another.  It is placed in this file     */
  69. /* because it needs close proximity to the  hide/show func- */
  70. /* tions.                                                   */
  71. /************************************************************/
  72.  
  73. int wndmove(WNDPTR *wnd, int row, int col) {
  74.  
  75.    int rw, cl;
  76.  
  77.    if (!chk_video_state(&rw,&cl)) return(0);
  78.    if (wnd->hideflag == USER) {                  /* If hidden then  */
  79.       change_wnd_position(wnd,row,col,cl,rw);    /* Change position */
  80.       return(1);                                 /* And return      */
  81.    }
  82.    if (chk_wnds(wnd)) {                          /* Remove overlapping winds */
  83.       hide_wnd(wnd, SYSTEM);                     /* Hide our wnd */
  84.       reshow_wnds(wnd->back);                    /* Show overlaps */
  85.       change_wnd_position(wnd,row,col,cl,rw);    /* Change our position */
  86.       show_wnd(wnd, SYSTEM);                     /* And Show it */
  87.    }
  88.    else {
  89.       hide_wnd(wnd, SYSTEM);                     /* No overlaps so hide */
  90.       change_wnd_position(wnd,row,col,cl,rw);    /* Change position */
  91.       show_wnd(wnd, SYSTEM);                     /* And show it     */
  92.    }
  93.    remove_from_list(wnd);                        /* Move wnd to first */
  94.    insert_first_in_list(wnd);                    /* In list */
  95.    level_wnds(topwnd);                           /* Relevel all windows */
  96.    return(1);                                    /* Return  */
  97. }
  98.  
  99. /***********************************************************/
  100. /*                    Change_Wnd_Position                  */
  101. /*                                                         */
  102. /* This function calculates the new position of a window.  */
  103. /* Checks that it will be in bounds of screen and adjusts  */
  104. /* if it is not.                                           */
  105. /***********************************************************/
  106.  
  107. static void change_wnd_position(WNDPTR *wnd,int row,int col,int cl,int rw) {
  108.  
  109.    int rows, cols;
  110.  
  111.    rows = (wnd->lrow - wnd->urow);            /* Calc total rows */
  112.    cols = (wnd->lcol - wnd->ucol);            /* Same for cols   */
  113.  
  114.    if (row < 1) row = 1;
  115.    if (col < 1) col = 1;
  116.  
  117.    if ((col + cols) >  cl) {                  /* Is it in bounds */
  118.       cl = (col + cols) - cl;
  119.       col = col - cl;
  120.    }
  121.  
  122.    if ((row + rows) > rw) {                   /* Is it in bounds? */
  123.       rw = (row + rows) - rw;                 /* No - Adjust the rows */
  124.       row= row - rw;
  125.    }
  126.  
  127.    wnd->urow = row;                           /* Save in wnd structure */
  128.    wnd->ucol = col;
  129.    wnd->lrow = row + rows;
  130.    wnd->lcol = col + cols;
  131. }
  132.  
  133. /************************************************************/
  134. /*                          Re_Order                        */
  135. /*                                                          */
  136. /* This function is the main driver for the window list     */
  137. /* management routines.  Its job, depending on the action to*/
  138. /* be taken is to handle the logic of managing how the      */
  139. /* windows are ordered visibly, and how they are ordered    */
  140. /* logically in the window list.                            */
  141. /************************************************************/
  142.  
  143. void re_order(WNDPTR *wnd, int action) {
  144.  
  145.    switch(action) {
  146.       case NORMAL :                         /* Bring window to surface */
  147.          if (wnd->level == 1) return;       /* If first in list-forget it */
  148.          if (chk_wnds(wnd)) {               /* If window overlap then */
  149.             hide_wnd(wnd, SYSTEM);          /* Hide our window     */
  150.             reshow_wnds(wnd->back);         /* Show those that were hid */
  151.             show_wnd(wnd, SYSTEM);          /* Put ours on top */
  152.          }
  153.          remove_from_list(wnd);             /* Remove from window list */
  154.          insert_first_in_list(wnd);         /* Make it the logical first */
  155.          break;
  156.  
  157.       case PUSH :                           /* Adding a new window to list */
  158.          insert_first_in_list(wnd);         /* Insert it first */
  159.          break;                             /* Over & Out! */
  160.  
  161.       case POP :                            /* For pops */
  162.          if (wnd->hideflag) {               /* If window hidden */
  163.             remove_from_list(wnd);          /* Remove it from list */
  164.             break;                          /* And get out */
  165.          }
  166.          if (wnd->level == 1) {             /* If first in list */
  167.             remove_from_list(wnd);          /* Remove it */
  168.             hide_wnd(wnd, SYSTEM);          /* Hide it */
  169.          }
  170.          else {
  171.             if (chk_wnds(wnd)) {            /* If someone overlaps */
  172.                 hide_wnd(wnd, SYSTEM);      /* Hide ours */
  173.                 reshow_wnds(wnd->back);     /* Reshow other windows */
  174.             }
  175.             else hide_wnd(wnd, SYSTEM);     /* No overlaps - so hide */
  176.             remove_from_list(wnd);          /* Remove from list */
  177.          }
  178.          break;
  179.  
  180.       case HIDE :
  181.          if (wnd->level == 1) {             /* If first window... */
  182.             hide_wnd(wnd, USER);            /* Hide it with user attribute */
  183.             return;                         /* and return */
  184.          }
  185.          if (chk_wnds(wnd)) {               /* Remove overlaps if any */
  186.             hide_wnd(wnd, USER);            /* Hide window with user attr */
  187.             reshow_wnds(wnd->back);         /* Reshow the overlaps */
  188.          }
  189.          else {
  190.             hide_wnd(wnd, USER);            /* No overlaps so just hide */
  191.             return;                         /* Return */
  192.          }
  193.          break;
  194.  
  195.       case SHOW :
  196.          if (wnd->hideflag != USER)         /* Do not try to show a  */
  197.             return;                         /* Window not hidden */
  198.          show_wnd(wnd, USER);               /* Show the window   */
  199.          remove_from_list(wnd);             /* Put the window first in */
  200.          insert_first_in_list(wnd);         /* List                    */
  201.          break;
  202.  
  203.    }
  204.    level_wnds(topwnd);                      /* Relevel the windows. */
  205. }
  206.  
  207.  
  208. /************************************************************/
  209. /*                     Remove_From_List                     */
  210. /*                                                          */
  211. /* This routine will remove a window from the window list.  */
  212. /* The logic is most likely more complicated than needed but*/
  213. /* better safe than sorry when worrying about null pointer  */
  214. /* assignments.                                             */
  215. /************************************************************/
  216.  
  217. static void remove_from_list(WNDPTR *wnd) {
  218.  
  219.    if (wnd->back == NULL) {                    /* Means its the top */
  220.       if (wnd->next == NULL)                   /* Means its the only one */
  221.          topwnd = (WNDPTR *) NULL;             /* Set the top to NULL */
  222.       else {
  223.          wnd->next->back = (WNDPTR *) NULL;    /* Set the back to NULL */
  224.          topwnd = wnd->next;                   /* Make the next on top */
  225.       }
  226.    }
  227.    else {                                      /* Its in middle or at end */
  228.       if (wnd->next == NULL)                   /* Its the end */
  229.          wnd->back->next = (WNDPTR *) NULL;    /* Cut it out of list */
  230.       else {                                   /* Its in the middle */
  231.          wnd->next->back = wnd->back;          /* Remove & reset all */
  232.          wnd->back->next = wnd->next;          /* the pointers */
  233.       }
  234.    }
  235. }
  236.  
  237. /************************************************************/
  238. /*                   Insert_First_In_List                   */
  239. /*                                                          */
  240. /* The name says it all.  A little logic to protect against */
  241. /* the dreaded "Null Pointer Assignment" message.           */
  242. /************************************************************/
  243. static void insert_first_in_list(WNDPTR *wnd) {
  244.  
  245.       wnd->next     = (WNDPTR *) topwnd;    /* Insert it first in list */
  246.       wnd->back     = (WNDPTR *) NULL;      /* Back always set to NULL */
  247.       if (topwnd != NULL)                   /* If topwnd = NULL then */
  248.          topwnd->back = wnd;                /* NO assignment PLEASE  */
  249.       topwnd        = wnd;                  /* Make our wnd first    */
  250. }
  251.  
  252. /*************************************************************/
  253. /*                           Chk_Wnds                        */
  254. /*                                                           */
  255. /* This routine recursively determines if a window is over-  */
  256. /* lapping another.  If a window is found to be overlapping  */
  257. /* it must hide that window, but first it must determine if  */
  258. /* a window above it is overlapping so it calls itself.      */
  259. /* It will work its way down - and up - the list removing    */
  260. /* all overlapping windows.                                  */
  261. /*************************************************************/
  262.  
  263. static int chk_wnds(WNDPTR *wnd) {
  264.  
  265.    WNDPTR *wrkwnd;
  266.    int    overlap;
  267.  
  268.    wrkwnd = topwnd;                          /* Start with top window */
  269.    overlap= 0;                               /* Set local auto to false */
  270.    while (wrkwnd->level < wnd->level) {      /* While 1 less than level */
  271.       if (!wrkwnd->hideflag) {               /* If its hidden forget it */
  272.          if (wnd_overlap(wrkwnd, wnd)) {     /* If they overlap */
  273.             overlap = 1;                     /* Set our switch */
  274.             chk_wnds(wrkwnd);                /* Recurse with new window */
  275.             hide_wnd(wrkwnd, SYSTEM);        /* Finally hide it */
  276.          }
  277.       }
  278.       wrkwnd = wrkwnd->next;                 /* Grab next window */
  279.    }
  280.    return (overlap);                         /* Return our switch setting */
  281. }
  282.  
  283. /************************************************************/
  284. /*                        Reshow_Wnds                       */
  285. /*                                                          */
  286. /* This function reshows any windows we had to hide along   */
  287. /* the way. It runs thru the list backwards to the beginning*/
  288. /************************************************************/
  289.  
  290. static void reshow_wnds(WNDPTR *wnd) {
  291.  
  292.    while (wnd) {                            /* Run Backwards thru the */
  293.        if (wnd->hideflag != USER)            /* If user attr skip */
  294.           show_wnd(wnd, SYSTEM);             /* List showing windows */
  295.        wnd = wnd->back;                      /* We pulled off */
  296.    }
  297. }
  298. /* */
  299. /************************************************************/
  300. /*                        Level_Wnds                        */
  301. /*                                                          */
  302. /* This funtion runs thru the list from the beginning and   */
  303. /* reassignes level values to each window after and inser-  */
  304. /* tion or deletion.                                        */
  305. /************************************************************/
  306.  
  307. static void level_wnds(WNDPTR *wnd) {
  308.  
  309.    int  i = 1;
  310.    WNDPTR *wrkwnd;
  311.  
  312.    wrkwnd = wnd;
  313.    while (wrkwnd) {                     /* While window pointer not NULL */
  314.         wrkwnd->level = i++;            /* Assign a new level number */
  315.         wrkwnd = wrkwnd->next;          /* Get next window */
  316.    }
  317. }
  318.  
  319. /************************************************************/
  320. /*                         Hide_Wnd                         */
  321. /*                                                          */
  322. /* This routine will hide a specified window with one of two*/
  323. /* attributes, USER & SYSTEM.  The system attribute means   */
  324. /* the window system is hiding the window for its own       */
  325. /* purposes and is a temporary hide while the user attribute*/
  326. /* means the user wanted to hide the window and leave it    */
  327. /* hidden until it is desired to be shown.  USER overrides  */
  328. /* SYSTEM, meaning if the system is running thru the list   */
  329. /* showing all SYSTEM hidden windows the USER hidden will   */
  330. /* be ignored.                                              */
  331. /************************************************************/
  332.  
  333. static int hide_wnd(WNDPTR *wnd, int attribute) {
  334.  
  335.    int  rows, cols, page, pagesize;
  336.    unsigned offset, scrnseg;
  337.    int far *scrnptr;
  338.  
  339.    if (wnd->hideflag) return(1);             /* Can't hide again */
  340.    if (wnd->wbuffer  == (char far *) NULL)
  341.       return(0);
  342.  
  343.    cols = (wnd->lcol - wnd->ucol) + 1;       /* Calc total cols */
  344.    rows = (wnd->lrow - wnd->urow) + 1;       /* And rows */
  345.    page = wnd->page;
  346.  
  347.    if (wnd->wsave == (char far *) NULL) {
  348.       wnd->wsave = (char far *) _fmalloc((rows * cols) * 2);
  349.       if (wnd->wsave == (char far *) NULL)
  350.          return(0);
  351.    }
  352.  
  353.    pagesize = getpagesize();
  354.    scrnseg  = getscrnseg();
  355.    offset   = MK_SCRNOFF(wnd->urow,wnd->ucol);
  356.    scrnptr  = (int far *) MK_FP(scrnseg, offset);
  357.  
  358.    SaveScrn(rows, cols, scrnptr, wnd->wsave);
  359.    RestoreScrn(rows, cols, scrnptr, wnd->wbuffer);
  360.    wnd->hideflag = attribute;
  361.    return(1);
  362. }
  363.  
  364. /************************************************************/
  365. /*                         Show_Wnd                         */
  366. /*                                                          */
  367. /* This function will show the windows that were hidden.    */
  368. /* If the show is with attribute SYSTEM and the window was  */
  369. /* hidden with USER we will bypass.                         */
  370. /************************************************************/
  371.  
  372. static int show_wnd(WNDPTR *wnd, int attribute) {
  373.  
  374.     int rows, cols, page, pagesize;
  375.     unsigned scrnseg, offset;
  376.     int far *scrnptr;
  377.  
  378.     if (wnd->wbuffer == NULL || wnd->wsave == NULL)  /* Exit if not */
  379.        return(0);                                    /* Ever allocated */
  380.  
  381.     if (wnd->hideflag != attribute)                  /* Can't show if */
  382.        return(0);                                    /* Attr don't match */
  383.  
  384.     wnd->hideflag = 0;                               /* Reset hideflag */
  385.     rows = (wnd->lrow - wnd->urow) + 1;              /* Calc total rows */
  386.     cols = (wnd->lcol - wnd->ucol) + 1;              /* And Cols */
  387.     page = wnd->page;                                /* Get the scrn page */
  388.  
  389.     scrnseg = getscrnseg();                          /* Get scrn segment */
  390.     pagesize= getpagesize();                         /* get pagesize */
  391.     offset  = MK_SCRNOFF(wnd->urow,wnd->ucol);       /* Calc offset */
  392.     scrnptr = (int far *) MK_FP(scrnseg, offset);    /* Make a far pointer */
  393.  
  394.     SaveScrn(rows, cols, scrnptr, wnd->wbuffer);     /* Save whats there */
  395.     RestoreScrn(rows, cols, scrnptr, wnd->wsave);    /* Put the wnd down */
  396.     return(1);                                       /* Return */
  397. }
  398.  
  399.  
  400. /************************************************************/
  401. /*                        Wnd_Overlap                       */
  402. /*                                                          */
  403. /* This routine determines if two windows overlap the same  */
  404. /* portion of the screen.  It is a bit difficult to tell how*/
  405. /* it works.  I had to draw myself some pictures of over-   */
  406. /* lapping windows to figure it out.                        */
  407. /************************************************************/
  408.  
  409. static int wnd_overlap(WNDPTR *wnd1, WNDPTR *wnd2) {
  410.  
  411.     if (wnd1->page != wnd2->page)          /* If not in same page */
  412.        return(0);                          /* they can't overlap  */
  413.  
  414.     if (((wnd2->ucol >= wnd1->ucol) && (wnd2->ucol <= wnd1->lcol)) &&
  415.        (((wnd2->urow >= wnd1->urow) && (wnd2->urow <= wnd1->lrow)) ||
  416.         ((wnd2->lrow >= wnd1->urow) && (wnd2->lrow <= wnd1->lrow))))
  417.             return(1);
  418.  
  419.     if (((wnd2->lcol >= wnd1->ucol) && (wnd2->lcol <= wnd1->lcol)) &&
  420.        (((wnd2->urow >= wnd1->urow) && (wnd2->urow <= wnd1->lrow)) ||
  421.         ((wnd2->lrow >= wnd1->urow) && (wnd2->lrow <= wnd1->lrow))))
  422.             return(1);
  423.  
  424.     if (((wnd1->ucol >= wnd2->ucol) && (wnd1->lcol <= wnd2->lcol)) &&
  425.        (((wnd1->urow >= wnd2->urow) && (wnd1->urow <= wnd2->lrow)) ||
  426.         ((wnd1->lrow >= wnd2->urow) && (wnd1->lrow <= wnd2->lrow))))
  427.             return(1);
  428.  
  429.     if (((wnd1->urow >= wnd2->urow) && (wnd1->lrow <= wnd2->lrow)) &&
  430.        (((wnd1->ucol >= wnd2->ucol) && (wnd1->ucol <= wnd2->lcol)) ||
  431.         ((wnd1->lcol >= wnd2->ucol) && (wnd1->lcol <= wnd2->lcol))))
  432.             return(1);
  433.  
  434.     if ((wnd1->ucol > wnd2->ucol && wnd1->lcol < wnd2->lcol) &&
  435.         (wnd1->urow > wnd2->urow && wnd1->lrow < wnd2->lrow))
  436.             return(1);
  437.  
  438.     return(0);
  439. }
  440.